package searcher;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.util.ArrayList;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.Filter;
import org.apache.lucene.search.FuzzyQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.NumericRangeQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.apache.lucene.search.BooleanClause;
import entity.Rent;

public class cnRentSearcher {
	
	public static TopDocs results;
	public static ScoreDoc[] hits;
	public static Document[] docs = new Document[1000];
	static int hitsperpage = 10;
	static int POWER = 1000;
	private static String index = new String("E:/Index/RentIndex");

	int price_l;
	int price_h;
	int room;
	int hall;
	String decoration;
	String stair;
	String direction;
	String region;
	
	public int precnRentSearch() throws Exception{
		IndexReader reader = DirectoryReader.open(FSDirectory.open(new File(index)));
		IndexSearcher searcher = new IndexSearcher(reader);
		Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_40);
		
		Filter filter;
		Query query = null;
		
		BooleanQuery bQuery = new BooleanQuery();
		
		if (this.price_l != -1 && this.price_h != -1){
			if (this.price_l == -1) this.setPrice_l(Integer.MIN_VALUE);
			if (this.price_h == -1) this.setPrice_l(Integer.MAX_VALUE);
			query = NumericRangeQuery.newIntRange("price", this.price_l, this.price_h, true, true);
			bQuery.add(query, BooleanClause.Occur.MUST);
		}
		
		if (room != -1){
			query = NumericRangeQuery.newIntRange("room", this.room , this.room, true, true);
			bQuery.add(query, BooleanClause.Occur.MUST);
		}
		if (hall != -1){
			query = NumericRangeQuery.newIntRange("hall", this.hall , this.hall, true, true);
			bQuery.add(query, BooleanClause.Occur.MUST);
		}
		if (this.decoration != null){
			query = new FuzzyQuery(new Term("decoration",this.getDecoration()));
			bQuery.add(query, BooleanClause.Occur.MUST);
		}
		if (this.stair != null){
			query = new TermQuery(new Term("stair",this.getStair()));
			bQuery.add(query, BooleanClause.Occur.MUST);
		}
		if (this.direction != null){
			query = new FuzzyQuery(new Term("direction",this.getDirection()));
			bQuery.add(query, BooleanClause.Occur.MUST);
		}
		if (this.region != null){
			query = new FuzzyQuery(new Term("region",this.getRegion()));
			bQuery.add(query, BooleanClause.Occur.MUST);
		}
		results = searcher.search(bQuery,POWER);
		hits = results.scoreDocs;
		int numTotalHits = results.totalHits;
		for (int i=0;i<Math.min(POWER,numTotalHits);i++){
			docs[i] = searcher.doc(hits[i].doc);
		}
		printasxml(1,"s");
		System.out.println(numTotalHits + " total matching documents");
		return ((numTotalHits+1)/hitsperpage+1);
	}
	
	public static void printasxml(int page, String locat) throws Exception{
		int min, max;
		if (page == -1)	{
			min = 0;
			max = results.totalHits;
		} else {
			min = (page-1)*hitsperpage;
			max = (page*hitsperpage>results.totalHits?results.totalHits:page*hitsperpage);
		}
		if (max > 986) max = 986;
		BufferedWriter bw = new BufferedWriter(new FileWriter("D:/cnRentResult.xml"));
		bw.write("<?xml version=\"1.0\" encoding=\"ANSI\"?>"); bw.newLine();
		bw.write("<searchResult type=\"cnRent\">"); bw.newLine();
		for(int i=min; i<max; i++){
			bw.write("\t<node id=" + i + "\">"); bw.newLine();
			bw.write("\t\t<region>" + docs[i].get("region") + "</region>"); bw.newLine();
			bw.write("\t\t<area>" + docs[i].get("area") + "</area>"); bw.newLine();
			bw.write("\t\t<stair>" + docs[i].get("stair") + "</stair>"); bw.newLine();
			bw.write("\t\t<house room=\"" + docs[i].get("room") + "\" hall=\"" + docs[i].get("hall") + "\"/>"); bw.newLine();
			bw.write("\t\t<year>" + docs[i].get("year") + "</year>"); bw.newLine();
			bw.write("\t\t<price>" + docs[i].get("price") + "</price>"); bw.newLine();
			bw.write("\t\t<imglink>" + docs[i].get("imglink") + "</imglink>"); bw.newLine();
			bw.write("\t</node>"); bw.newLine();
		}
		bw.write("</searchResult>"); bw.newLine();
		bw.close();
		return;
	}
	
	public ArrayList<Rent> getResultatPage(int page){
		ArrayList<Rent> resultList = new ArrayList<Rent>();
		for (int i=(page-1)*hitsperpage; i<page*hitsperpage;i++){
			if (i>=results.totalHits) return resultList;
			System.out.println("doc="+hits[i].doc+" score="+hits[i].score+",");
			Rent e = new Rent();
			e.setArea(docs[i].get("area"));
			e.setBuild(docs[i].get("build"));
			e.setCommlink("");
			e.setDecoration(docs[i].get("decoration"));
			e.setDirection(docs[i].get("direction"));
			e.setHouse(docs[i].get("room")+"室"+docs[i].get("hall")+"厅");
			e.setImglink(docs[i].get("imglink"));
			e.setRegion(docs[i].get("region"));
			e.setPrice(docs[i].get("price"));
			e.setStair(docs[i].get("stair"));
			e.setYear(docs[i].get("year"));
			resultList.add(e);
		}
		return resultList;
	}
	
	public cnRentSearcher(int price_l, int price_h, int room, int hall,
			String decoration, String stair, String direction,
			String region) {
		super();
		this.price_l = price_l;
		this.price_h = price_h;
		this.room = room;
		this.hall = hall;
		this.decoration = decoration;
		this.stair = stair;
		this.direction = direction;
		this.region = region;
	}

	public int getPrice_l() {
		return price_l;
	}

	public void setPrice_l(int price_l) {
		this.price_l = price_l;
	}

	public int getPrice_h() {
		return price_h;
	}

	public void setPrice_h(int price_h) {
		this.price_h = price_h;
	}

	public int getRoom() {
		return room;
	}

	public void setRoom(int room) {
		this.room = room;
	}

	public int getHall() {
		return hall;
	}

	public void setHall(int hall) {
		this.hall = hall;
	}

	public String getDecoration() {
		return decoration;
	}

	public void setDecoration(String decoration) {
		this.decoration = decoration;
	}

	public String getStair() {
		return stair;
	}

	public void setStair(String stair) {
		this.stair = stair;
	}

	public String getDirection() {
		return direction;
	}

	public void setDirection(String direction) {
		this.direction = direction;
	}

	public String getRegion() {
		return region;
	}

	public void setRegion(String region) {
		this.region = region;
	}
}